// https://www.nowcoder.com/practice/fd55637d3f24484e96dad9e992d3f62e?tpId=230&tqId=2032484&ru=/exam/oj&qru=/ta/dynamic-programming/question-ranking&sourceUrl=/exam/oj?page=1&tab=%25E7%25AE%2597%25E6%25B3%2595%25E7%25AF%2587&topicId=196

// 算法思路总结：
// 1. 滚动数组优化0-1背包问题（两种变体）
// 2. 第一问：经典背包，求不超过容量的最大价值
// 3. 第二问：恰好装满背包的最大价值（未装满记为-1）
// 4. 状态定义：dp[j]表示容量为j时的最大价值
// 5. 倒序遍历避免物品重复选择（0-1背包特性）
// 6. 时间复杂度：O(n×V)，空间复杂度：O(V)

#include <iostream>
using namespace std;

#include <vector>
#include <algorithm>
#include <cstring>

const int N = 1010;
int v[N], w[N];
int dp[N];

int main() 
{
    int n, V;
    cin >> n >> V;

    for (int i = 1 ; i <= n ; i++)
    {
        cin >> v[i] >> w[i];
    }

    for (int i = 1 ; i <= n ; i++)
    {
        for (int j = V ; j >= 0 ; j--)
        {
            if (j - v[i] >= 0)
            {
                dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
            }
        }
    }
    cout << dp[V] << endl;

    memset(dp, 0, sizeof(dp));
    for (int j = 1 ; j <= V ; j++)
    {
        dp[j] = -1;
    }

    for (int i = 1 ; i <= n ; i++)
    {
        for (int j = V ; j >= 0; j--)
        {
            if (j - v[i] >= 0 && dp[j - v[i]] != -1)
            {
                dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
            }
        }
    }
    cout << (dp[V] == -1 ? 0 : dp[V]) << endl;

    return 0;
}
